package telnetserver;

import java.net.*;
import java.util.ArrayList;

public class User extends Thread {
    private Socket socket;
    private boolean run;
    private int skip;
    private int arrow;
    private int[] logon = { 255, 251, 1, 255, 253, 3, 255, 251, 3 };
    private int maxLength;
    private ArrayList<Integer> in;
    private String nick;
    private Object mode;
    private String tot;
    private boolean canWrite;
    private boolean canPress;
    private Telnet telnet;
    private String[] chat;
    private int fixX;
    private int fixY;
    private int fixL;
    private String msg;
    private int score;
    private boolean ready;
    private boolean buying;
    private int cash;
    private int[] weapon;
    private boolean playing;
    
    private int button;
    private int vButton;
    private int hButton;
    private String[] vButtons;
    private String[] hButtons;
    private int[][] vxy;
    private int[][] hxy;
    private int vx;
    private int vy;
    private int hx;
    private int hy;
    private int voffset;
    private int hoffset;
    
    public User(Telnet t, Socket s, Login l) {
        for (int i : logon) {
            try {
                s.getOutputStream().write(i);
            } catch (Exception e) {}
        }
        telnet = t;
        in = new ArrayList<Integer>();
        socket = s;
        run = true;
        skip = 0;
        maxLength = 10;
        mode = l;
        button = 1;
        tot = "";
        canWrite = true;
        canPress = false;
        button = 0;
        nick = "";
        score = 0;
        ready = false;
        buying = false;
        cash = 3000;
        weapon = new int[3];
        playing = false;
        chat = new String[20];
        for (int j = 0; j < chat.length; j++) {
            chat[j] = "";
        }
        fixX = 0;
        fixY = 0;
        fixL = 0;
        msg = "";
        vButtons = new String[0];
        hButtons = new String[0];
        vxy = new int[0][0];
        hxy = new int[0][0];
    }
    
    public void run() {
        try {
            while (run) {
                int i = socket.getInputStream().read();
                if (i == 255) skip = 4;
                else if (i == 27) {
                    skip = 4;
                    arrow = 3;
                }
                if (i < 0) run = false;
                
                if (skip > 0) skip--;
                if (arrow > 0) arrow--;
                if (arrow == 0) {
                    arrow = -1;
                    i -= 64;
                    if (i > 0 && i < 5 && canPress) {
                        if (vButton >= 0 || hButton >= 0) {
                            int too = 0;
                            int vh = -1;
                            switch (i) {
                                case 1:
                                    too = vButton - 1;
                                    if (too < 0) too = vButtons.length - 1;
                                    if (vButton >= 0) vh = 0;
                                    break;
                                case 2:
                                    too = vButton + 1;
                                    if (too >= vButtons.length) too = 0;
                                    if (vButton >= 0) vh = 0;
                                    break;
                                case 3:
                                    too = hButton + 1;
                                    if (too >= hButtons.length) too = 0;
                                    if (hButton >= 0) vh = 1;
                                    break;
                                case 4:
                                    too = hButton - 1;
                                    if (too < 0) too = hButtons.length - 1;
                                    if (hButton >= 0) vh = 1;
                                    break;
                            }
                            if (vh >= 0) changeButton(vh, too);
                        } else {
                            Class[] parameterTypes = { User.class, int.class };
                            mode.getClass().getMethod("buttonPressed", parameterTypes).invoke(mode, this, i);
                        }
                    }
                }
                
                if (skip == 0) {
                    if ( i > 30 && i < 127 && in.size() < maxLength && canWrite) {
                        in.add(i);
                        if (fixL == 0 || in.size() < fixL) socket.getOutputStream().write(i);
                        else {
                            String s = "";
                            for (int j = in.size() - fixL; j < in.size(); j++) {
                                s += (char)(int)in.get(j);
                            }
                            prepare(fixX, fixY, s);
                            send();
                        }
                    }
                    
                    if (i == 13) {
                        String s = "";
                        for (int i2 : in) {
                            s += (char)i2;
                        }
                        Class[] parameterTypes = { User.class, String.class };
                        mode.getClass().getMethod("read", parameterTypes).invoke(mode, this, s);
                        in.clear();
                    } else if (i == 8 || i == 127) {
                        if (in.size() > 0) {
                            in.remove(in.size() - 1);
                            if (fixL == 0 || in.size() < fixL) socket.getOutputStream().write(((char)27 + "[1D " + (char)27 + "[1D").getBytes());
                            else {
                                String s = "";
                                for (int j = in.size() - fixL; j < in.size(); j++) {
                                    s += (char)(int)in.get(j);
                                }
                                prepare(fixX, fixY, s);
                                send();
                            }
                        }
                    } else if (i == 145) {
                        if (in.size() < maxLength - 1) {
                            in.add(65);
                            in.add(69);
                            socket.getOutputStream().write(65);
                            socket.getOutputStream().write(69);
                        }
                    } else if (i == 155) {
                        if (in.size() < maxLength - 1) {
                            in.add(79);
                            in.add(69);
                            socket.getOutputStream().write(79);
                            socket.getOutputStream().write(69);
                        }
                        
                    } else if (i == 134) {
                        if (in.size() < maxLength - 1) {
                            in.add(65);
                            in.add(65);
                            socket.getOutputStream().write(65);
                            socket.getOutputStream().write(65);
                        }
                    } else if (i == 230) {
                        if (in.size() < maxLength - 1) {
                            in.add(65);
                            in.add(69);
                            socket.getOutputStream().write(65);
                            socket.getOutputStream().write(69);
                        }
                    } else if (i == 248) {
                        if (in.size() < maxLength - 1) {
                            in.add(79);
                            in.add(69);
                            socket.getOutputStream().write(79);
                            socket.getOutputStream().write(69);
                        }
                        
                    } else if (i == 229) {
                        if (in.size() < maxLength - 1) {
                            in.add(65);
                            in.add(65);
                            socket.getOutputStream().write(65);
                            socket.getOutputStream().write(65);
                        }
                    }
                }
            }
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
            clear();
            prepare(1, 1, "Oh noes! A error occured!");
            prepare(1, 2, "ERROR: " + e);
            send();
        }
        telnet.remUser(this);
    }
    
    public void send(int x, int y, String s) {
        try {
            socket.getOutputStream().write(((char)27 + "[" + y + ";" + x + "H" + s).getBytes());
        } catch (Exception e) {}
    }
    
    public void send(int type, int x, int y, String s) {
        try {
            socket.getOutputStream().write(((char)27 + "[" + y + ";" + x + "H" +
                    (char)27 + "[" + type + "m" + s + (char)27 + "[" + type + "m").getBytes());
        } catch (Exception e) {}
    }
    
    public void prepare(int x, int y, String s) {
        tot += (char)27 + "[" + y + ";" + x + "H" + s;
    }
    
    public void prepare(int type, int x, int y, String s) {
        tot += (char)27 + "[" + y + ";" + x + "H" +(char)27 + "[" + type + "m" + s + (char)27 + "[" + type + "m";
    }
    
    public void prepare(int type) {
        tot += (char)27 + "[" + type + "m";
    }
    
    public void prepare(String s) {
        tot += s;
    }
    
    public void send(String s) {
        try {
            socket.getOutputStream().write(s.getBytes());
        } catch (Exception e) {}
    }
    
    public void send() {
        try {
            socket.getOutputStream().write(tot.getBytes());
            tot = "";
        } catch (Exception e) {}
    }
    
    public void clear() {
        tot = (char)27 + "[2J";
    }
    
    public void clear(int lineNr) {
        try {
            socket.getOutputStream().write(((char)27 + "[" + lineNr + ";0H" + (char)27 + "[2K").getBytes());
        } catch (Exception e) {}
    }
    
    public void closeSocket() {
        run = false;
        try {
            socket.close();
        } catch (Exception e) {}
    }
    
    public Object getMode() {
        return mode;
    }
    
    public void setMode(Object o) {
        mode = o;
    }
    
    public int[] getButton() {
        int[] all = new int[2];
        all[0] = button;
        if (button == 0) all[1] = vButton;
        else all[1] = hButton;
        return all;
    }
    
    
    public void setButton(int i) {
        button = i;
    }
    
    //      BUTTONS INTERFACE! YEAH! **********************************************************
    
    public void setButtons(String[] newVButtons, String[] newHButtons) {
        vButton = 0;
        hButton = 0;
        button = 0;
        if (newHButtons != null) {
            hButtons = newHButtons;
            hxy = new int[hButtons.length][2];
            button = 1;
        } else hButton = -1;
        if (newVButtons != null) {
            vButtons = newVButtons;
            vxy = new int[vButtons.length][2];
        } else vButton = -1;
    }
    
    public void fixButtonsXY(int newvx, int newvy, int newvoffset, int newhx, int newhy, int newhoffset) {
        vx = newvx;
        vy = newvy;
        hx = newhx;
        hy = newhy;
        voffset = newvoffset;
        hoffset = newhoffset;
        
        if (vButton >= 0) {
            for (int i = 0; i < vButtons.length; i++) {
                vxy[i][0] = vx;
                vxy[i][1] = vy + i * voffset;
            }
        }
        if (hButton >= 0) {
            int tot = hx;
            for (int i = 0; i < hButtons.length; i++) {
                hxy[i][0] = tot;
                hxy[i][1] = hy;
                tot += hoffset + hButtons[i].length();
            }
        }
    }
    
    public void fixButtonsXY(int x, int y, int offset) {
        if (vButton >= 0) {
            for (int i = 0; i < vButtons.length; i++) {
                vxy[i][0] = x;
                vxy[i][1] = y + i * offset;
            }
        } else if (hButton >= 0) {
            int tot = x;
            for (int i = 0; i < hButtons.length; i++) {
                hxy[i][0] = tot;
                hxy[i][1] = y;
                tot += offset + hButtons[i].length();
            }
        }
    }
    
    public void fixButtonsXY() {
        if (vButton >= 0) {
            vxy = new int[vButtons.length][2];
            for (int i = 0; i < vButtons.length; i++) {
                vxy[i][0] = vx;
                vxy[i][1] = vy + i * voffset;
            }
        } else if (hButton >= 0) {
            int tot = hx;
            hxy = new int[hButtons.length][2];
            for (int i = 0; i < hButtons.length; i++) {
                hxy[i][0] = tot;
                hxy[i][1] = hy;
                tot += hoffset + hButtons[i].length();
            }
        }
    }
    
    public void drawButtons() {
        if (vButton >= 0) {
            for (int i = 0; i < vButtons.length; i++) {
                prepare(vxy[i][0], vxy[i][1], vButtons[i]);
            }
            changeButton(0, 0);
        }
        if (hButton >= 0) {
            for (int i = 0; i < hButtons.length; i++) {
                prepare(hxy[i][0], hxy[i][1], hButtons[i]);
            }
            changeButton(1, 0);
        }
        prepare(0, 80, "");
        send();
    }
    
    public void changeButton(int vh, int btn) {
        if (vh != button) {
            if (vh == 0) btn = vButton;
            else btn = hButton;
        }
        tot += (char)27 + "[s";
        if (button == 0 && vButtons.length > 0) prepare(1, vxy[vButton][0], vxy[vButton][1], vButtons[vButton]);
        else if (button == 1 && hButtons.length > 0) prepare(1, hxy[hButton][0], hxy[hButton][1], hButtons[hButton]);
        
        if (vh == 0 && vButtons.length > 0) {
            prepare(7, vxy[btn][0], vxy[btn][1], vButtons[btn]);
            vButton = btn;
        } else if (vh == 1 && hButtons.length > 0) {
            prepare(7, hxy[btn][0], hxy[btn][1], hButtons[btn]);
            hButton = btn;
        }
        button = vh;
        tot += (char)27 + "[u";
        send();
    }
    
    public void addButton(int vh, String s) {
        String[] buttons = new String[0];
        if (vh == 0) buttons = vButtons;
        else buttons = hButtons;
        String[] temp = new String[buttons.length + 1];
        for (int i = 0; i < buttons.length; i++) {
            temp[i] = buttons[i];
        }
        temp[buttons.length] = s;
        if (vh == 0) {
            vButtons = new String[temp.length];
            for (int i = 0; i < temp.length; i++) {
                vButtons[i] = temp[i];
            }
        } else {
            hButtons = new String[temp.length];
            for (int i = 0; i < temp.length; i++) {
                hButtons[i] = temp[i];
            }
        }
        fixButtonsXY();
        drawButtons();
    }
    
    public void remButton(int vh, String s) {
        System.out.println("rem button! " + s);
        try {
            String[] buttons = new String[0];
            if (vh == 0) buttons = vButtons;
            else buttons = hButtons;
            String[] temp = new String[buttons.length - 1];
            int i2 = 0;
            for (int i = 0; i < buttons.length; i++) {
                if (!s.equals(buttons[i])) {
                    temp[i2] = buttons[i];
                    i2++;
                } else {
                    if (button == vh) {
                        if (vh == 0 && i >= vButton && vButton > 0) vButton--;
                        else if (vh == 1 && i >= hButton && vButton > 0) hButton--;
                    }
                }
            }
            if (vh == 0) {
                vButtons = new String[temp.length];
                for (int i = 0; i < temp.length; i++) {
                    vButtons[i] = temp[i];
                }
            } else {
                hButtons = new String[temp.length];
                for (int i = 0; i < temp.length; i++) {
                    hButtons[i] = temp[i];
                }
            }
            fixButtonsXY();
            drawButtons();
        } catch (Exception e) {
            e.printStackTrace();
            
        }
        
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    public boolean canWrite() {
        return canWrite;
    }
    
    public void setCanWrite(boolean b) {
        canWrite = b;
    }
    
    public boolean canPress() {
        return canPress;
    }
    
    public void setCanPress(boolean b) {
        canPress = b;
    }
    
    public String getNick() {
        return nick;
    }
    
    public void setNick(String s) {
        nick = s;
    }
    
    public void addchat(String s) {
        for(int i = 1; i < chat.length - 1; i++) {
            chat[i] = chat[i + 1];
        }
        chat[chat.length - 1] = s;
    }
    
    public String[] getChat() {
        return chat;
    }
    
    public int getInLength() {
        return in.size();
    }
    
    public void setMaxLength(int i) {
        maxLength = i;
    }
    
    public void setFix(int x, int y, int l) {
        fixX = x;
        fixY = y;
        fixL = l;
    }
    
    public void setMsg(String s) {
        msg = s;
    }
    
    public String getMsg() {
        return msg;
    }
    
    public int getScore() {
        return score;
    }
    
    public void setScore(int i) {
        score = i;
    }
    
    public boolean getReady() {
        return ready;
    }
    
    public void setReady(boolean b) {
        ready = b;
    }
    
    public boolean getBuying() {
        return buying;
    }
    
    public void setBuying(boolean b) {
        buying = b;
    }
    
    public int getCash() {
        return cash;
    }
    
    public void setCash(int i) {
        cash = i;
    }
    
    public int getWeapon(int i) {
        return weapon[i];
    }
    
    public void setWeapon(int wep, int i) {
        weapon[wep] = i;
    }
    
    public boolean getPlaying() {
        return playing;
    }
    
    public void setPlaying(boolean b) {
        playing = b;
    }
}